/*****************************************************\
* Copyright (c) 2020 The game2d Authors. All rights reserved.
  Use of this source code is governed by a BSD-style license that can be
  found in the LICENSE file.

* Author:         dzlua - https://gitee.com/dzlua/game2d.git
* Email:          505544956@qq.com
* FileName:       utils/utils.cc
* Create Time:    2020/03/21 12:25:14
* Description:    /
\****************************************************/
#include "utils.h"

#include "ctrls/control.h"


namespace g2d {
namespace utils {
  extern bool colormap_find(const char *k, unsigned int &v);
  
  Uint8 parse_hex(const char c, Uint8 def) {
    if (c >= '0' && c <= '9') return (c - '0');
    if (c >= 'A' && c <= 'F') return (c - 'A' + 10);
    if (c >= 'a' && c <= 'f') return (c - 'a' + 10);
    return def;
  }
  bool parse_bool(const char *value, bool def) { if (!value) return def; return strcmp(value, "true") == 0; }
  int parse_int(const char *value, int def) { if (!value) return def; return atoi(value); }
  Uint32 parse_uint32(const char *value, Uint32 def) { if (!value) return def; char *p; return strtoul(value, &p, 10); }
  float parse_float(const char *value, float def) {  if (!value) return def; char *p; return strtof(value, &p); }
  SDL_FPoint parse_pos(const char *value, float def) {
    SDL_FPoint pt; char *p;
    if (!value) {
      pt.x = def;
      pt.y = def;
    } else {
      pt.x = strtof(value, &p);
      pt.y = strtof(p+1, &p);
    }
    return std::move(pt);
  }
  Sizei parse_sizei(const char *value, int def) {
    Sizei sz; char *p;
    if (!value) {
      sz.w = sz.h = def;
    } else {
      sz.w = (int)strtol(value, &p, 10);
      sz.h = (int)strtol(p+1, &p, 10);
    }
    return std::move(sz);
  }
  Size parse_size(const char *value, float def) {
    Size sz; char *p;
    if (!value) {
      sz.h = sz.w = def;
    } else {
      sz.w = strtof(value, &p);
      sz.h = strtof(p+1, &p);
    }
    return std::move(sz);
  }
  SDL_Color parse_color(const char *value, Uint8 def) {
    SDL_Color c = { def };
    if (!value) return std::move(c);

    if (value[0] == '#') {
      auto len = strlen(value+1);
      if (len == 3) {
        c.a = 255;
        c.r = parse_hex(value[1]) * 17;
        c.g = parse_hex(value[2]) * 17;
        c.b = parse_hex(value[3]) * 17;
      } else if (len == 6) {
        c.a = 255;
        c.r = parse_hex(value[1]) * 16 + parse_hex(value[2]);
        c.g = parse_hex(value[3]) * 16 + parse_hex(value[4]);
        c.b = parse_hex(value[5]) * 16 + parse_hex(value[6]);
      } else if (len == 8) {
        c.a = parse_hex(value[1]) * 16 + parse_hex(value[2]);
        c.r = parse_hex(value[3]) * 16 + parse_hex(value[4]);
        c.g = parse_hex(value[5]) * 16 + parse_hex(value[6]);
        c.b = parse_hex(value[7]) * 16 + parse_hex(value[8]);
      }
    } else {
      unsigned v;
      if (colormap_find(value, v)) {
        c.a = 255;
        c.r = (Uint8) (v >> 16);
        c.g = (Uint8) (v >> 8);
        c.b = (Uint8) (v >> 0);
      }
    }
    return std::move(c);
  }
  g2d::TextureData parse_image(const char *value) {
    g2d::TextureData d;
    int pos = 0;
    if (value) {
      while (value[pos]) {
        if (value[pos] == ':') break;
        ++pos;
      }
    }
    if (pos > 0) {
      d.id.assign(value, pos);
      if (value[pos+1]) {
        char *p;
        d.src.x = strtof(value+pos+1, &p);
        d.src.y = strtof(p+1, &p);
        d.src.w = strtof(p+1, &p);
        d.src.h = strtof(p+1, &p);
      }
    }
    return std::move(d);
  }
  g2d::ctrl::HorAlign parse_halign(const char *value) {
    if (strcmp(value, "center") == 0) return g2d::ctrl::HorAlign::Center;
    else if (strcmp(value, "right") == 0) return g2d::ctrl::HorAlign::Right;
    else return g2d::ctrl::HorAlign::Left;
  }
  g2d::ctrl::VerAlign parse_valign(const char *value) {
    if (strcmp(value, "middle") == 0) return g2d::ctrl::VerAlign::Middle;
    else if (strcmp(value, "bottom") == 0) return g2d::ctrl::VerAlign::Bottom;
    else return g2d::ctrl::VerAlign::Top;
  }
  g2d::ctrl::Inset parse_inset(const char *value, float def) {
    char *p;
    g2d::ctrl::Inset inset;
    if (!value) {
      inset.l = inset.t = inset.r = inset.b = def;
    } else {
      inset.l = strtof(value, &p);
      inset.t = strtof(p+1, &p);
      inset.r = strtof(p+1, &p);
      inset.b = strtof(p+1, &p);
    }
    return std::move(inset);
  }
} // end namespace utils
} // end namespace g2d